function l(msg) {
    console.log(msg);
}
function f2() {
    "use strict";//strict mode
    return this;
}
// l(f2() === undefined);
//role as object
var o = {
    prop: 37,
    f: function () {
        return this.prop;
    }
}
// l(o.f());
//原型链上的this
var o = {
    f: function () {
        return this.a + this.b;
    }
}
var p = Object.create(o);
p.a = 1;
p.b = 4;
// l(p.f());  这里需要注意的是p的原型才是o，我们调用p.f()，
// 调用的是原型链o上的属性f，原型链上的this可以拿到当前的对象p。

//get/set方法与this
function modulus() {
    return Math.sqrt(this.re * this.re + this.im * this.im);
}
var o = {
    re: 1,
    im: -1,
    get phrase() {
        return Math.atan2(this.im, this.re);
    }
};
// Object.defineProperties(o, modulus);
// Object.defineProperties(o,{get:modulus,enumerable:true,configurable:true})
// l(o.phrase);  //?????????????不明白
// l(o.modulus);
//构造函数中的this
function Myclass() {
    this.a = 37;
}
var o = new Myclass();
l(o.a);
function C2() {
    this.a = 37;
    return {
        a: 40
    }  //返回了一个对象
}
var o = new C2();
l(o.a === 40);
//call/apply方法与this
/*除了不同的调用方式外，函数对象有些方法能修改函数执行的this，比如call/apply。

 call和apply基本上没差别，只不过call传参的方式是扁平的，而apply是把一个数组传进去。如下面这个例子

 什么时候用call和apply呢？比如我们想调用Object.prototype.toString,但是我们想指定某个this的时候，那我们就可以就用
 Object.prototype.toString.call(this)这样子的方式来调用些无法直接调用的方法。*/
function add(c, d) {
    return this.a + this.b + c + d;
}
var o = {
    a: 1,
    b: 3
};
var a1 = add.call(o, 2, 3);
var a2 = add.apply(o, [2, 3]);
l(a1);
l(a2);
function bar() {
    l(Object.prototype.toString.call(this))
}
bar.call(7);
//bind 与this
function f() {
    return this.a;
}

var g = f.bind({a: "test"});   //想把某个对象作为this的时候，就把它传进去，得到一个新对象g
console.log(g()); // test       //重复调用的时候，this已经指向bind参数。这对于我们绑定一次需要重复调用依然实现绑定的话，会比apply和call更加高效（看下面这个例子）

var o = {a: 37, f: f, g: g};
console.log(o.f(), o.g());
// 37, test   //o.f()通过对象的属性调用，this指向对象o;
// 比较特殊的是即使我们把新绑定的方法作为对象的属性调用，
// o.g()依然会按之前的绑定去走，所以答案是test不是g